package cn.shadow.moulde;

import com.esotericsoftware.reflectasm.MethodAccess;
import com.google.common.base.Preconditions;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class Module implements IModule {
    static final int MIN_MODULE_ID = 0;
    static final int MAX_MODULE_ID = 127;
    private static final Logger logger = LoggerFactory.getLogger(Module.class);
    private final int moduleId;
    private final Class<?> msgCls;
    private final Handler[] handlers;
    private boolean isClosed;
    protected final Logger moduleLog = LoggerFactory.getLogger(getClass());
    public Module() {
        Class<?> modCls = this.getClass();
        String modClsName = modCls.getName();
        Preconditions.checkArgument(modClsName.endsWith("Module"), "模块名字不是以Module结尾，是不是被混淆了？ %s", new Object[]{this});
        String msgClsName = modClsName + "Messages";

        try {
            this.msgCls = Class.forName(msgClsName);
        } catch (ClassNotFoundException var5) {
            throw new RuntimeException("模块消息类没有找到!" + msgClsName);
        }

        this.moduleId = this.initModuleId();
        this.handlers = this.initHandlers();
    }

    public final void dispatch(int msgId, ByteBuf buffer, IModuleObjController controller) {
        if (this.isClosed()) {
            logger.debug("Module.dispatch(), 模块已经被关闭，无法处理消息!{}, MsgId = {}", this, msgId);
        } else {
            Handler handler = this.getHandler(msgId);
            if (handler == null) {
                logger.error("Module.dispatch(), 未知的消息!{}, MsgId = {}", this, msgId);
            } else {
                handler.handle(buffer, controller);
            }
        }
    }

    private static boolean isValidModuleId(int moduleId) {
        return moduleId >= 0 && moduleId <= 127;
    }

    public int getModuleId() {
        return this.moduleId;
    }

    public final Class<?> getMsgCls() {
        return this.msgCls;
    }


    private Handler getHandler(int msgId) {
        return this.handlers[msgId];
    }

    public boolean isClosed() {
        return this.isClosed;
    }

    public void doClose() {
        this.isClosed = true;
        Handler[] handlers = this.handlers;
        int length = handlers.length;

        for (int i = 0; i < length; ++i) {
            Handler handler = handlers[i];
            if (handler != null) {
                handler.doClose();
            }
        }

    }

    public void doOpen() {
        this.isClosed = false;
        Handler[] handlers = this.handlers;
        int length = handlers.length;

        for (int i = 0; i < length; ++i) {
            Handler handler = handlers[i];
            if (handler != null) {
                handler.doOpen();
            }
        }

    }

    public void doCloseHandler(int msgId) {
        Handler handler = this.getHandler(msgId);
        if (handler == null) {
            logger.error("Module.doCloseHandler() {} 没有协议 = {} 的处理!", this, msgId);
        } else {
            handler.doClose();
        }
    }

    public void doOpenHandler(int msgId) {
        Handler handler = this.getHandler(msgId);
        if (handler == null) {
            logger.error("Module.doOpenHandler() {} 没有协议 = {} 的处理!", this, msgId);
        } else {
            handler.doOpen();
        }
    }


    private int initModuleId() {
        try {
            Field field = this.msgCls.getField("MODULE_ID");
            int moduleId = field.getInt(null);
            Preconditions.checkArgument(isValidModuleId(moduleId), "%s 模块id非法!", new Object[]{this});
            return moduleId;
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException var3) {
            logger.error("Module.initModuleId() 消息类 {} 中没有字段 MODULE_ID!", this.msgCls);
            throw new RuntimeException(var3);
        }
    }

    private Handler[] initHandlers() {
        MethodAccess methodAccess = MethodAccess.get(this.getClass());
        Handler[] handlers = new Handler[0];
        Method[] var3 = this.getClass().getDeclaredMethods();
        int var4 = var3.length;

        for (int var5 = 0; var5 < var4; ++var5) {
            Method method = var3[var5];
            AHandler handler = method.getAnnotation(AHandler.class);
            if (handler != null) {
                int msgId = handler.value();
                Preconditions.checkArgument(!Modifier.isPrivate(method.getModifiers()), "%s 方法 %s 注解了@IHandler的方法，不能够是private方法!", new Object[]{this, method.getName()});
                method.setAccessible(true);
                Handler newHandler = new Handler(methodAccess, this, method, handler);
                if (msgId >= handlers.length) {
                    handlers = Arrays.copyOf(handlers, msgId + 1);
                }

                Handler oldHandler = handlers[msgId];
                Preconditions.checkArgument(oldHandler == null, "%s 有多个 %s 协议!", new Object[]{this, msgId});
                handlers[msgId] = newHandler;
            }
        }

        return handlers;
    }

    public String toString() {
        return "ClassName: " + this.getClass().getSimpleName() + ", ModuleId = " + this.getModuleId();
    }
}
